package jp.ac.u_tokyo.dch.util.front;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.xwork.StringUtils;

import jp.ac.u_tokyo.dch.model.xml.DisplayDefine;
import jp.ac.u_tokyo.dch.model.xml.FrontInfo;
import jp.ac.u_tokyo.dch.model.xml.FrontItem;
import jp.ac.u_tokyo.dch.model.xml.Item;
import jp.ac.u_tokyo.dch.model.xml.Line;
/**
 * @version 1.1
 */
public class FrontDisplayUtil {


	private static String NO_SETTING = "";
	/**
	 * Col位置
	 */
	private static enum ColNumber{ ONE, TWO, THREE, FOUR };

	/**
	 * ユーザから入力した情報を元にフロント表示用オブジェクトを生成する
	 * @param frontInfo フロント情報
	 * @return 画面定義オブジェクト
	 */
	public static DisplayDefine frontInfoToDefine(FrontInfo frontInfo) {


		Map<String, List<Integer>> map = setEqualRow(frontInfo);
		int maxColumn = getMaxColumn(frontInfo);

		DisplayDefine define = new DisplayDefine();

		define.setItemColumnSu(String.valueOf(maxColumn));

		List<Line> list = new ArrayList<Line>();

		Integer rows1 = null;
		Integer rows2 = null;
		Integer rows3 = null;

		define.setList(list);

		String col1Before = null;
		String col2Before = null;
		String col3Before = null;

		for (FrontItem frontItem :frontInfo.getList()) {

			Line line = new Line();
			List<Item> itemList = new ArrayList<Item>();
			line.setKey(frontItem.getKey());
			line.setItemList(itemList);
			list.add(line);

			int maxSetColumn = getMaxColumnSet(frontItem);

			String col1 = frontItem.getCol1();
			String col2 = frontItem.getCol2();
			String col3 = frontItem.getCol3();
			String col4 = frontItem.getCol4();

			if (StringUtils.isEmpty(col1)) {
				col1 = NO_SETTING;
			}
			if (maxSetColumn > 2 && StringUtils.isEmpty(col2)) {
				col2 = NO_SETTING;
			}
			if (maxSetColumn > 3 && StringUtils.isEmpty(col3)) {
				col3 = NO_SETTING;
			}


			if (maxSetColumn == 1) {

				getRowCountByMap(map, col1Before, col2Before, col1, ColNumber.ONE);

				Item item1 = new Item();
				item1.setRowspan("1");
				item1.setColspan(String.valueOf(maxColumn));
				item1.setValue(col1);
				itemList.add(item1);

			} else if (maxSetColumn == 2) {

				rows1 = getRowCountByMap(map, col1Before, col2Before, col1, ColNumber.ONE);

				if (rows1 != null) {

					//map.remove(convertLvKey(col1, ColNumber.ONE));
					Item item1 = new Item();
					item1.setRowspan(rows1.toString());
					item1.setColspan(String.valueOf(getColumnNum1(frontItem, maxColumn)));
					item1.setValue(col1);
					itemList.add(item1);

					Item item2 = new Item();
					item2.setRowspan("1");
					item2.setColspan(String.valueOf(getColumnNum2(frontItem, maxColumn)));
					item2.setValue(col2);
					itemList.add(item2);

				} else {

					Item item2 = new Item();
					item2.setRowspan("1");
					item2.setColspan(String.valueOf(getColumnNum2(frontItem, maxColumn)));
					item2.setValue(col2);
					itemList.add(item2);
				}


			} else if (maxSetColumn == 3) {

				rows1 = getRowCountByMap(map, col1Before, col2Before, col1, ColNumber.ONE);
				rows2 = getRowCountByMap(map, col2Before, col3Before, col2, ColNumber.TWO);


				if (rows1 != null) {

					//map.remove(convertLvKey(col1, ColNumber.ONE));
					Item item1 = new Item();
					item1.setRowspan(rows1.toString());
					item1.setColspan(String.valueOf(getColumnNum1(frontItem, maxColumn)));
					item1.setValue(col1);
					itemList.add(item1);


					if (rows2 != null) {

						//map.remove(convertLvKey(col2, ColNumber.TWO));

						Item item2 = new Item();
						item2.setRowspan(rows2.toString());
						item2.setColspan(String.valueOf(getColumnNum2(frontItem, maxColumn)));
						item2.setValue(col2);
						itemList.add(item2);

						Item item3 = new Item();
						item3.setRowspan("1");
						item3.setColspan(String.valueOf(getColumnNum3(frontItem, maxColumn)));
						item3.setValue(col3);
						itemList.add(item3);


					} else {

						Item item3 = new Item();
						item3.setRowspan("1");
						item3.setColspan(String.valueOf(getColumnNum3(frontItem, maxColumn)));
						item3.setValue(col3);
						itemList.add(item3);

					}

				} else {

					if (rows2 != null) {

						//map.remove(convertLvKey(col2, ColNumber.TWO));

						Item item2 = new Item();
						item2.setRowspan(rows2.toString());
						item2.setColspan(String.valueOf(getColumnNum2(frontItem, maxColumn)));
						item2.setValue(col2);
						itemList.add(item2);

						Item item3 = new Item();
						item3.setRowspan("1");
						item3.setColspan(String.valueOf(getColumnNum3(frontItem, maxColumn)));
						item3.setValue(col3);
						itemList.add(item3);


					} else {

						Item item3 = new Item();
						item3.setRowspan("1");
						item3.setColspan(String.valueOf(getColumnNum3(frontItem, maxColumn)));
						item3.setValue(col3);
						itemList.add(item3);

					}
				}


			} else {

				rows1 = getRowCountByMap(map, col1Before, col2Before, col1, ColNumber.ONE);
				rows2 = getRowCountByMap(map, col2Before, col3Before, col2, ColNumber.TWO);
				rows3 = getRowCountByMap(map, col3Before, "", col3, ColNumber.THREE);

				if (rows1 != null) {

					//map.remove(convertLvKey(col1, ColNumber.ONE));
					Item item1 = new Item();
					item1.setRowspan(rows1.toString());
					item1.setColspan(String.valueOf(getColumnNum1(frontItem, maxColumn)));
					item1.setValue(col1);
					itemList.add(item1);


					if (rows2 != null) {

						//map.remove(convertLvKey(col2, ColNumber.TWO));

						Item item2 = new Item();
						item2.setRowspan(rows2.toString());
						item2.setColspan(String.valueOf(getColumnNum2(frontItem, maxColumn)));
						item2.setValue(col2);
						itemList.add(item2);

						if (rows3 != null) {

							//map.remove(convertLvKey(col3, ColNumber.THREE));

							Item item3 = new Item();
							item3.setRowspan(rows3.toString());
							item3.setColspan(String.valueOf(getColumnNum3(frontItem, maxColumn)));
							item3.setValue(col3);
							itemList.add(item3);

							Item item4 = new Item();
							item4.setRowspan("1");
							item4.setColspan("1");
							item4.setValue(col4);
							itemList.add(item4);

						} else {

							Item item4 = new Item();
							item4.setRowspan("1");
							item4.setColspan("1");
							item4.setValue(col4);
							itemList.add(item4);
						}
					} else {

						if (rows3 != null) {

							//map.remove(convertLvKey(col3, ColNumber.THREE));

							Item item3 = new Item();
							item3.setRowspan(rows3.toString());
							item3.setColspan(String.valueOf(getColumnNum3(frontItem, maxColumn)));
							item3.setValue(col3);
							itemList.add(item3);

							Item item4 = new Item();
							item4.setRowspan("1");
							item4.setColspan("1");
							item4.setValue(col4);
							itemList.add(item4);

						} else {

							Item item4 = new Item();
							item4.setRowspan("1");
							item4.setColspan("1");
							item4.setValue(col4);
							itemList.add(item4);
						}
					}
				} else {

					if (rows2 != null) {

						//map.remove(convertLvKey(col2, ColNumber.TWO));

						Item item2 = new Item();
						item2.setRowspan(rows2.toString());
						item2.setColspan(String.valueOf(getColumnNum2(frontItem, maxColumn)));
						item2.setValue(col2);
						itemList.add(item2);

						if (rows3 != null) {

							//map.remove(convertLvKey(col3, ColNumber.THREE));

							Item item3 = new Item();
							item3.setRowspan(rows3.toString());
							item3.setColspan(String.valueOf(getColumnNum3(frontItem, maxColumn)));
							item3.setValue(col3);
							itemList.add(item3);

							Item item4 = new Item();
							item4.setRowspan("1");
							item4.setColspan("1");
							item4.setValue(col4);
							itemList.add(item4);

						} else {

							Item item4 = new Item();
							item4.setRowspan("1");
							item4.setColspan("1");
							item4.setValue(col4);
							itemList.add(item4);

						}
					} else {

						if (rows3 != null) {

							//map.remove(convertLvKey(col3, ColNumber.THREE));

							Item item3 = new Item();
							item3.setRowspan(rows3.toString());
							item3.setColspan(String.valueOf(getColumnNum3(frontItem, maxColumn)));
							item3.setValue(col3);
							itemList.add(item3);

							Item item4 = new Item();
							item4.setRowspan("1");
							item4.setColspan("1");
							item4.setValue(col4);
							itemList.add(item4);

						} else {

							Item item4 = new Item();
							item4.setRowspan("1");
							item4.setColspan("1");
							item4.setValue(col4);
							itemList.add(item4);
						}
					}
				}
			}


			col1Before = col1;
			col2Before = col2;
			col3Before = col3;
		}


		return define;
	}

	private static Integer getRowCountByMap(Map<String, List<Integer>> map, String beforeCol1, String beforeCol2,String col, ColNumber colNum) {

		Integer rowCount = null;

		if (beforeCol1 == null || !beforeCol1.equals(col) || (beforeCol1.equals(col) && beforeCol2 == null)) {
			List<Integer> list = map.get(convertLvKey(col, colNum));
			rowCount = list.remove(0);
		}

		return rowCount;
	}


	/**
	 * COl1のColspanを求める
	 * @param frontItem FLEX画面から入力した表示情報
	 * @param column カラム番号
	 * @return Colspan
	 */
	private static int getColumnNum1(FrontItem frontItem, int column) {

		String col2 = frontItem.getCol2();
		String col3 = frontItem.getCol3();
		String col4 = frontItem.getCol4();

		if (StringUtils.isEmpty(col2) && StringUtils.isEmpty(col3) && StringUtils.isEmpty(col4)) {
			return column;
		}

		return 1;

	}

	/**
	 * COl2のColspanを求める
	 * @param frontItem FLEX画面から入力した表示情報
	 * @param column カラム番号
	 * @return Colspan
	 */
	private static int getColumnNum2(FrontItem frontItem, int column) {

		String col3 = frontItem.getCol3();
		String col4 = frontItem.getCol4();

		if (StringUtils.isEmpty(col3) && StringUtils.isEmpty(col4)) {
			return column - 1;
		}

		return 1;

	}
	/**
	 * COl3のColspanを求める
	 * @param frontItem FLEX画面から入力した表示情報
	 * @param column カラム番号
	 * @return Colspan
	 */
	private static int getColumnNum3(FrontItem frontItem, int column) {

		String col4 = frontItem.getCol4();

		if (StringUtils.isEmpty(col4)) {
			return column - 2;
		}
		return 1;

	}


	/**
	 * FLEX画面から何番目まで入力されているかを精査
	 * @param front FLEX画面から入力した表示情報
	 * @return 最大設定されているCOL
	 */
	private static int getMaxColumn(FrontInfo front) {

		int i = 1;

		for (FrontItem frontItem :front.getList()) {

			String col2 = frontItem.getCol2();
			String col3 = frontItem.getCol3();
			String col4 = frontItem.getCol4();

			if (StringUtils.isNotEmpty(col4)) {
				return 4;
			}

			if (StringUtils.isNotEmpty(col3)) {
				i = 3;
			}
			if (StringUtils.isNotEmpty(col2)) {

				if (i < 2) {
					i = 2;
				}
			}
		}
		return i;
	}

	/**
	 * COL番号によってユニークキー生成
	 * @param col COL表示名
	 * @param colNum Col番号
	 * @return ユニークキー
	 */
	private static String convertLvKey(String col, ColNumber colNum) {

		switch (colNum) {
		case ONE:
			return "COL1" + col;
		case TWO:
			return "COL2" + col;
		case THREE:
			return "COL3" + col;
		case FOUR:
			return "COL4" + col;
		default:
			return null;
		}
	}


	/**
	 * 直下の名前を調べて同じCOL名があればCOL名によるカウンタをする
	 * @param front FLEX画面から入力した表示情報
	 * @return COL名とカウンタのマップ
	 */
	private static Map<String, List<Integer>> setEqualRow(FrontInfo front) {

		Map<String, List<Integer>> colInfo = new HashMap<String, List<Integer>>();

		String col1Before = null;
		String col2Before = null;
		String col3Before = null;


		for (FrontItem frontItem :front.getList()) {

			int columnSu = getMaxColumnSet(frontItem);

			String col1 = frontItem.getCol1();
			String col2 = frontItem.getCol2();
			String col3 = frontItem.getCol3();
			String col4 = frontItem.getCol4();

			if (StringUtils.isEmpty(col1)) {
				col1 = NO_SETTING;
			}
			if (StringUtils.isEmpty(col2)) {
				col2 = NO_SETTING;
			}
			if (StringUtils.isEmpty(col3)) {
				col3 = NO_SETTING;
			}

			if (col1Before == null || (StringUtils.isEmpty(col2) && StringUtils.isEmpty(col3) && StringUtils.isEmpty(col4))) {

				setEqualsRows(convertLvKey(col1, ColNumber.ONE), colInfo);

			} else if (col1Before.equals(col1) && col2Before != null) {

				addEqualsRows(convertLvKey(col1, ColNumber.ONE), colInfo);

			} else {
				setEqualsRows(convertLvKey(col1, ColNumber.ONE), colInfo);

			}

			col1Before = col1;

			if (columnSu >= 2) {

				if (col2Before == null || (StringUtils.isEmpty(col3) && StringUtils.isEmpty(col4))) {

					setEqualsRows(convertLvKey(col2, ColNumber.TWO), colInfo);

				} else if (col2Before.equals(col2) && col3Before != null) {

					addEqualsRows(convertLvKey(col2, ColNumber.TWO), colInfo);
				} else {

					setEqualsRows(convertLvKey(col2, ColNumber.TWO), colInfo);

				}

				col2Before = col2;
			} else {
				col2Before = null;
			}

			if (columnSu >= 3) {

				if (col3Before == null || StringUtils.isEmpty(col4)) {

					setEqualsRows(convertLvKey(col3, ColNumber.THREE), colInfo);

				} else if (col3Before.equals(col3)) {

					addEqualsRows(convertLvKey(col3, ColNumber.THREE), colInfo);
				} else {

					setEqualsRows(convertLvKey(col3, ColNumber.THREE), colInfo);

				}

				col3Before = col3;
			} else {
				col3Before = null;
			}

		}

		return colInfo;
	}

	private static void addEqualsRows(String key, Map<String, List<Integer>> colInfo) {

		List<Integer> list = colInfo.get(key);

		int size = list.size();

		Integer rows = list.get(size - 1);

		list.set(size - 1, ++rows);

	}

	private static void setEqualsRows(String key, Map<String, List<Integer>> colInfo) {

		List<Integer> list = null;

		if (colInfo.containsKey(key)) {

			list = colInfo.get(key);

			list.add(Integer.valueOf(1));

		} else {

			list = new ArrayList<Integer>();

			list.add(Integer.valueOf(1));

			colInfo.put(key, list);
		}
	}

	/**
	 * 表示単位毎の最大設定されているカラム番号
	 * @param frontItem FLEX画面から入力した表示情報
	 * @return MaxColumn
	 */
	private static int getMaxColumnSet(FrontItem frontItem) {

		String col2 = frontItem.getCol2();
		String col3 = frontItem.getCol3();
		String col4 = frontItem.getCol4();

		if (StringUtils.isNotEmpty(col4)) {
			return 4;
		}

		if (StringUtils.isNotEmpty(col3)) {
			return 3;
		}

		if (StringUtils.isNotEmpty(col2)) {
			return 2;
		}
		return 1;
	}

}
